#ifndef INTERFACE_COMPONENT_HPP
#define INTERFACE_COMPONENT_HPP

#include "GlobalDefines.hpp"
#include "state/App.hpp"
#include "sfml/Graphics.hpp"
#include "Event.hpp"
#include "utils/Log.hpp"

#include "graphics/VertexBuffer.hpp"
#include "graphics/IndexBuffer.hpp"
#include "graphics/VertexArray.hpp"
#include "graphics/ShaderObject.hpp"

namespace mi
{

  struct UIvertex
  {
    Vec3f position;
    Vec3f color;
    Vec2f texcoord;
    float alpha;
  };

  struct UIface
  {
    Vec3i verts;
  };

  class UIvertexDecl : public VertexDecl
  {
  public:
     UIvertexDecl()
     {
        AddElement(VertexElement(Position, GL_FLOAT, 3, 0));
        AddElement(VertexElement(Color,    GL_FLOAT, 3, 12));
        AddElement(VertexElement(Texcoord, GL_FLOAT, 2, 24));
        AddElement(VertexElement(Alpha,    GL_FLOAT, 1, 32));
     }
  };

  /*
  Widget coord and size interpretation
  

      +-----------------+
      |       ^         |
      |       |         |
      |     size.x      |
      |                 |
      | <- size.y       |
      |                 |
      |                 |
      X-----------------+
      ^
      Position


  */

  enum WidgetType
  {
    tButton,
    tTextbox,
    tCycleButton,
    tCheckbox,
    tRadioButton,
    tWindow,
    tView
  };

  class Widget
  {
  public:
    Widget(WidgetType type, std::string newText = "", std::string ID = "");

    ~Widget();

    void SetID(std::string newID);

    void SetText(std::string newText);

    std::string GetID();

    std::string GetInternalID();

    std::string GetText();

    WidgetType GetType();

    // TODO: These should not be public to be honest, but for now this solution may work
    void SetSize (Vec2i size);
    
    void SetPos (Vec2i pos);

    Vec2i GetSize ();

    Vec2i GetPos ();

    // Function to check if this widget contains or is the one passed in. Only needs to be overriden if widget contains other widgets

    virtual bool Contains(Widget* other);

    // Input functions may be overriden

    virtual Widget* MouseClick(sf::Mouse::Button button, sf::MouseState state, int x, int y);
    
    virtual Widget* MouseMoved(int x, int y, int dx, int dy);
    
    virtual Widget* MouseDragged(int x, int y, int dx, int dy);
    
    virtual Widget* MouseWheel(int dir);
    
    virtual Widget* KeysDown(sf::Event::KeyEvent key);
    
    virtual Widget* KeysUp(sf::Event::KeyEvent key);

    virtual Widget* TextEntered(char ch);

    // Draw2D and Update must be overriden by children

    virtual void Draw2D () = 0;

    virtual bool Update (double dTime) = 0;

    static void OnResize (int w, int h);

  protected:

    void SetTextPos(sf::Text &txt, Vec2i pos);

    void RenderText (sf::Text txt);

    Vec2i GetTextSize (std::string txt);

    void DrawBackground (Vec2i start, Vec2i end);

    void DrawFace (Vec2i start, Vec2i end);

    void DrawTitle (Vec2i start, Vec2i end);

    bool IsMouseInBody (Vec2i mouse);

    virtual void OnTextChanged();

    virtual void OnSizeChange(Vec2i oldSize);

    virtual void OnPositionChange(Vec2i oldPosition);

    std::string text;

    std::string ID;

    WidgetType type;

    Vec2i size, position;

    void DrawQuad(Vec2i start, Vec2i end, sf::Texture *texture = NULL, Vec3d topColor = Vec3d(0, 0, 0), unsigned int opacity = 128 );

    void DrawNinePatch(Vec2i start, Vec2i end,
                       int left, int top, int right, int bottom,
                       int imgLeft, int imgTop, int imgRight, int imgBottom,
                       sf::Texture *texture);

    static sf::Font defaultFont;

    static int defaultFontSize;

    static int appw, apph;

  private:

    static int widgetCount;

    static unsigned long uniqueid;

    static std::string GenerateUniqueID();

    static sf::RectangleShape quad;

    static sf::Text sizableText;
    
    static int lineHeight;

    static bool defaultFontNotInit;

    static sf::Texture *titlebarTexture;

    static sf::Texture *TMP_TEST_TEX;

  };
}

#endif